#include "sc2143.h"
#include "hal_i2c.h"
#include "i2c.h"
#include "hal_gpio.h"
#include "hal.h"
#include "hal_dvp.h"
#include "../isp_xc6130/xc6130.h"

//#include "i2c_ll.h"


static STRU_CAMERA_REG_VALUE SC2143_default_regs[] = {
	// SC2143_1920x1080_SET 
		
    0x0100,0x00,
    0x3c00,0x45, //FIFO RESET

    0x3907,0x01, //RNC BLC
    0x3908,0xc0,
    0x3416,0x10,

    0x3200,0x00,
    0x3201,0x00,
    0x3204,0x07,
    0x3205,0x9f,
    0x322c,0x07,
    0x322d,0xa8,
    0x322e,0x07,
    0x322f,0xff,
    0x3400,0x53,
    0x3401,0x1e,
    0x3402,0x04,
    0x3403,0x30,

    0x3637,0x87,//RAMP

    0x3623,0x02,//analog
    0x3620,0xc4,
    0x3621,0x18,

    0x3635,0x03,

    //Timing

    0x3300,0x10,//EQ
    0x3306,0xc0,
    0x330a,0x01,
    0x330b,0xa0,

    0x3333,0x00, 
    0x3334,0x20,

    0x3039,0x00, //74.25M pclk
    0x303a,0x35,
    0x303b,0x0c,
    0x3034,0x07,
    0x3035,0x4a,
    0x320c,0x08, //0x898 for 30fps
    0x320d,0x98,
    0x3211,0x10,
    0x3213,0x10,

    //0x301c,0xa4,//close mipi
    //0x3018,0xff, 

    0x3d08,0x00, //pclk inv

    0x337f,0x03, //new auto precharge  330e in 3372
    0x3368,0x04,
    0x3369,0x00,
    0x336a,0x00,
    0x336b,0x00,
    0x3367,0x08,
    0x330e,0x40,

    //0x3630/0x3635/0x3620 auto ctrl
    0x3670,0x0b, //bit[3] for 3635 in 3687, bit[1] for 3630 in 3686,bit[0] for 3620 in 3685
    0x3674,0xa0, //3630 value <gain0
    0x3675,0x90, //3630 value between gain0 and gain1
    0x3676,0x40, //3630 value > gain1
    0x367c,0x07, //gain0
    0x367d,0x0f, //gain1

    0x3677,0x0a, //3635 value <gain0
    0x3678,0x07, //3635 value between gain0 and gain1
    0x3679,0x07, //3635 value > gain1
    0x367e,0x07, //gain0
    0x367f,0x1f, //gain1

    0x3671,0xc2, //3620 value <gain0  11.23
    0x3672,0xc2, //3620 value between gain0 and gain1  11.23
    0x3673,0x63, //3620 value > gain1  11.23
    0x367a,0x07, //gain0
    0x367b,0x1f, //gain1



    0x3e03,0x03, //AE
    0x3e01,0x46,
    0x3e08,0x00,


    0x3401,0x1e,
    0x3402,0x00, 
    0x3403,0x48, //increase rnc col num to 72+16=88


    0x5781,0x08, //dpc
    0x5782,0x08,
    0x5785,0x20,
    0x57a2,0x01,
    0x57a3,0xf1,


    //fullwell
    0x3637,0x86,
    0x3635,0x03,
    0x3622,0x0e,
    0x3630,0x00, 
    0x3630,0x00, 
    0x3631,0x80,
    0x3633,0x54,

    //mipi
    0x3c00,0x41, //FIFO RESET for mipi
    0x3001,0xfe,
    0x303f,0x01, //[7] 0:sel pll_pclk

    0x3018,0x13, //lanenum=[7:5]+1
    0x3031,0x0a, // 10bit

    0x3039,0x00,
    0x303a,0x1f,
    0x303b,0x0e,
    0x303c,0x08,

    0x3306,0xf0,
    0x330b,0xd0,

    0x320c,0x08, //0x898 for 30fps
    0x320d,0x98,
    0x320e,0x04, //vts=1200
    0x320f,0xb0,

    0x320a,0x04, //1080
    0x320b,0x38,

    0x3650,0x46,
    0x3651,0x0c,

    0x3e09,0x10,

    //fullwell adjust 0907
    0x3637,0x87,
    0x3674,0xd0,
    0x3677,0x07,
    0x3633,0x74,


    0x3333,0x80, //col fpn
    0x3334,0xa0,
    0x3300,0x20, //shading
    0x3632,0x40, //gain >8 0x42

    //0908 update rnc num
    0x3403,0x58,
    0x3416,0x11,

    0x3302,0x28, //rst go low point to cancel left column fpn from rst
    0x3309,0x20, //ramp gap to cancel right column fpn from tx
    0x331f,0x17,
    0x3321,0x1a,

    0x3677,0x0b, //high txvdd when gain<2
    0x3678,0x08, //3635 value between gain0 and gain1
    0x3679,0x06, //3635 value > gain1

    0x3306,0xd0,


    //ECO
    0x322e,0x08, //rnc
    0x322f,0x37,
    0x3403,0x78,

    0x3679,0x08,

    //1118
    0x3679,0x06,
    0x3620,0xc4, //0x64

    //1122
    0x3637,0x84,
    0x3638,0x84,

     
    0x0100,0x01,  
			
};

static STRU_CAMERA_REG_VALUE SC2143_regs_1080p30fps[] = 
{
0x0100,0x00,
0x3c00,0x45, //FIFO RESET

0x3907,0x01, //RNC BLC
0x3908,0xc0,
0x3416,0x10,

0x3200,0x00,
0x3201,0x00,
0x3204,0x07,
0x3205,0x9f,
0x322c,0x07,
0x322d,0xa8,
0x322e,0x07,
0x322f,0xff,
0x3400,0x53,
0x3401,0x1e,
0x3402,0x04,
0x3403,0x30,

0x3637,0x87,//RAMP

0x3623,0x02,//analog
0x3620,0xc4,
0x3621,0x18,

0x3635,0x03,

//Timing

0x3300,0x10,//EQ
0x3306,0xc0,
0x330a,0x01,
0x330b,0xa0,

0x3333,0x00, 
0x3334,0x20,

0x3039,0x00, //74.25M pclk
0x303a,0x35,
0x303b,0x0c,
0x3035,0xca,
0x320c,0x08, //0x898 for 30fps
0x320d,0x98,
0x3211,0x10,
0x3213,0x10,

//0x301c,0xa4,//close mipi
//0x3018,0xff, 

0x3d08,0x00, //pclk inv

0x337f,0x03, //new auto precharge  330e in 3372
0x3368,0x04,
0x3369,0x00,
0x336a,0x00,
0x336b,0x00,
0x3367,0x08,
0x330e,0x40,

//0x3630/0x3635/0x3620 auto ctrl
0x3670,0x0b, //bit[3] for 3635 in 3687, bit[1] for 3630 in 3686,bit[0] for 3620 in 3685
0x3674,0xa0, //3630 value <gain0
0x3675,0x90, //3630 value between gain0 and gain1
0x3676,0x40, //3630 value > gain1
0x367c,0x07, //gain0
0x367d,0x0f, //gain1

0x3677,0x0a, //3635 value <gain0
0x3678,0x07, //3635 value between gain0 and gain1
0x3679,0x07, //3635 value > gain1
0x367e,0x07, //gain0
0x367f,0x1f, //gain1

0x3671,0xc2, //3620 value <gain0  11.23
0x3672,0xc2, //3620 value between gain0 and gain1  11.23
0x3673,0x63, //3620 value > gain1  11.23
0x367a,0x07, //gain0
0x367b,0x1f, //gain1



0x3e03,0x03, //AE
0x3e01,0x46,
0x3e08,0x00,


0x3401,0x1e,
0x3402,0x00, 
0x3403,0x48, //increase rnc col num to 72+16=88


0x5781,0x08, //dpc
0x5782,0x08,
0x5785,0x20,
0x57a2,0x01,
0x57a3,0xf1,


//fullwell
0x3637,0x86,
0x3635,0x03,
0x3622,0x0e,
0x3630,0x00, 
0x3630,0x00, 
0x3631,0x80,
0x3633,0x54,

//mipi
0x3c00,0x41, //FIFO RESET for mipi
0x3001,0xfe,
0x303f,0x01, //[7] 0:sel pll_pclk

0x3018,0x33, //lanenum=[7:5]+1
0x3031,0x0a, // 10bit

0x3039,0x00,
0x303a,0x31,
0x303b,0x06,
0x303c,0x08,

0x3306,0xf0,
0x330b,0xd0,

0x320c,0x09, //0x960 for 30fps
0x320d,0x60,

0x3650,0x46,
0x3651,0x0c,

0x3e09,0x10,

//fullwell adjust 0907
0x3637,0x87,
0x3674,0xd0,
0x3677,0x07,
0x3633,0x74,


0x3333,0x80, //col fpn
0x3334,0xa0,
0x3300,0x20, //shading
0x3632,0x40, //gain >8 0x42

//0908 update rnc num
0x3403,0x58,
0x3416,0x11,

0x3302,0x28, //rst go low point to cancel left column fpn from rst
0x3309,0x20, //ramp gap to cancel right column fpn from tx
0x331f,0x17,
0x3321,0x1a,

0x3677,0x0b, //high txvdd when gain<2
0x3678,0x08, //3635 value between gain0 and gain1
0x3679,0x06, //3635 value > gain1

0x3306,0xe0,


//ECO
0x322e,0x08, //rnc
0x322f,0x37,
0x3403,0x78,

0x3679,0x08,

//1118
0x3679,0x06,
0x3620,0xc4, //0x64

//1122
0x3637,0x84,
0x3638,0x84,

//170304
0x3039,0x50,
0x303a,0x53,
0x303b,0x06,
0x303c,0x08,
0x3035,0xba,

//0314
0x330e,0x20,
0x3308,0x20, //Lag
0x3632,0x40,
0x3676,0x38,

//20170314B
0x3676,0x0f,

//phy add
0x3200,0x00,
0x3201,0x00,
0x3202,0x00,
0x3203,0x00,
0x3204,0x07,
0x3205,0x9f, // xend = 1951
0x3206,0x04,
0x3207,0x57, // yend = 1111
0x3208,0x07,
0x3209,0x88, // 1928
0x320a,0x04,
0x320b,0x40, // 1088

//0418
0x3035,0xd2, // counterclk = 162M
0x3637,0x83, // ramp
0x3621,0x08,
0x330b,0xf8,
0x3306,0xd0,
0x3213,0x0a,
0x3223,0x50, // first frame
0x3364,0x05,

0x3e01,0x8c,

//20170109
0x3631,0x80,

0x0100,0x01,

};

static STRU_CAMERA_REG_VALUE SC2143_regs_1080p30fps_600fov[] = 
{
0x0100,0x00,
0x3c00,0x45, //FIFO RESET

0x3907,0x01, //RNC BLC
0x3908,0xc0,
0x3416,0x10,

0x3200,0x00,
0x3201,0x00,
0x3204,0x07,
0x3205,0x9f,
0x322c,0x07,
0x322d,0xa8,
0x322e,0x07,
0x322f,0xff,
0x3400,0x53,
0x3401,0x1e,
0x3402,0x04,
0x3403,0x30,

0x3637,0x87,//RAMP

0x3623,0x02,//analog
0x3620,0xc4,
0x3621,0x18,

0x3635,0x03,

//Timing

0x3300,0x10,//EQ
0x3306,0xc0,
0x330a,0x01,
0x330b,0xa0,

0x3333,0x00, 
0x3334,0x20,

0x3039,0x00, //74.25M pclk
0x303a,0x35,
0x303b,0x0c,
0x3035,0xca,
0x320c,0x08, //0x898 for 30fps
0x320d,0x98,
0x3211,0x10,
0x3213,0x10,

//0x301c,0xa4,//close mipi
//0x3018,0xff, 

0x3d08,0x00, //pclk inv

0x337f,0x03, //new auto precharge  330e in 3372
0x3368,0x04,
0x3369,0x00,
0x336a,0x00,
0x336b,0x00,
0x3367,0x08,
0x330e,0x40,

//0x3630/0x3635/0x3620 auto ctrl
0x3670,0x0b, //bit[3] for 3635 in 3687, bit[1] for 3630 in 3686,bit[0] for 3620 in 3685
0x3674,0xa0, //3630 value <gain0
0x3675,0x90, //3630 value between gain0 and gain1
0x3676,0x40, //3630 value > gain1
0x367c,0x07, //gain0
0x367d,0x0f, //gain1

0x3677,0x0a, //3635 value <gain0
0x3678,0x07, //3635 value between gain0 and gain1
0x3679,0x07, //3635 value > gain1
0x367e,0x07, //gain0
0x367f,0x1f, //gain1

0x3671,0xc2, //3620 value <gain0  11.23
0x3672,0xc2, //3620 value between gain0 and gain1  11.23
0x3673,0x63, //3620 value > gain1  11.23
0x367a,0x07, //gain0
0x367b,0x1f, //gain1



0x3e03,0x03, //AE
0x3e01,0x46,
0x3e08,0x00,


0x3401,0x1e,
0x3402,0x00, 
0x3403,0x48, //increase rnc col num to 72+16=88


0x5781,0x08, //dpc
0x5782,0x08,
0x5785,0x20,
0x57a2,0x01,
0x57a3,0xf1,


//fullwell
0x3637,0x86,
0x3635,0x03,
0x3622,0x0e,
0x3630,0x00, 
0x3630,0x00, 
0x3631,0x80,
0x3633,0x54,

//mipi
0x3c00,0x41, //FIFO RESET for mipi
0x3001,0xfe,
0x303f,0x01, //[7] 0:sel pll_pclk

0x3018,0x33, //lanenum=[7:5]+1
0x3031,0x0a, // 10bit

0x3039,0x00,
0x303a,0x31,
0x303b,0x06,
0x303c,0x08,

0x3306,0xf0,
0x330b,0xd0,

0x320c,0x09, //0x960 for 30fps
0x320d,0x60,

0x3650,0x46,
0x3651,0x0c,

0x3e09,0x10,

//fullwell adjust 0907
0x3637,0x87,
0x3674,0xd0,
0x3677,0x07,
0x3633,0x74,


0x3333,0x80, //col fpn
0x3334,0xa0,
0x3300,0x20, //shading
0x3632,0x40, //gain >8 0x42

//0908 update rnc num
0x3403,0x58,
0x3416,0x11,

0x3302,0x28, //rst go low point to cancel left column fpn from rst
0x3309,0x20, //ramp gap to cancel right column fpn from tx
0x331f,0x17,
0x3321,0x1a,

0x3677,0x0b, //high txvdd when gain<2
0x3678,0x08, //3635 value between gain0 and gain1
0x3679,0x06, //3635 value > gain1

0x3306,0xe0,


//ECO
0x322e,0x08, //rnc
0x322f,0x37,
0x3403,0x78,

0x3679,0x08,

//1118
0x3679,0x06,
0x3620,0xc4, //0x64

//1122
0x3637,0x84,
0x3638,0x84,

//170304
0x3039,0x50,
0x303a,0x53,
0x303b,0x06,
0x303c,0x08,
0x3035,0xba,

//0314
0x330e,0x20,
0x3308,0x20, //Lag
0x3632,0x40,
0x3676,0x38,

//20170314B
0x3676,0x0f,

//phy add
0x3200,0x00,
0x3201,0x00,
0x3202,0x00,
0x3203,0x00,
0x3204,0x07,
0x3205,0x9f, // xend = 1951
0x3206,0x04,
0x3207,0x57, // yend = 1111
0x3208,0x07,
0x3209,0x88, // 1928
0x320a,0x04,
0x320b,0x40, // 1088

//0418
0x3035,0xd2, // counterclk = 162M
0x3637,0x83, // ramp
0x3621,0x08,
0x330b,0xf8,
0x3306,0xd0,
0x3213,0x0a,
0x3223,0x50, // first frame
0x3364,0x05,

0x3e01,0x8c,

//20170109
0x3631,0x82,

0x0100,0x01,
};

int32_t SC2143_WriteReg(uint16_t u16_sc2143Reg, uint8_t u8_sc2143Val)
{
    uint8_t u8_buf[3] = {0};
    int32_t s32_result = 0;

    u8_buf[0] = u16_sc2143Reg >> 8;
    u8_buf[1] = u16_sc2143Reg & 0xff;
    u8_buf[2] = u8_sc2143Val;

    I2C_Master_WriteData(SC2143_COMPONENT, SC2143_I2C_ADDR, u8_buf, 3);
    s32_result = I2C_Master_WaitTillIdle(SC2143_COMPONENT, SC2143_I2C_MAX_DELAY);
    if(0 != s32_result)
    {
        DLOG_Error("write reg error:reg=%x,val=%x", u16_sc2143Reg, u8_sc2143Val);
        s32_result = -1;
    }
    else
    {
        ;
    }

    return s32_result;
}

int32_t SC2143_ReadReg(uint16_t u16_sc2143Reg, uint8_t *pu8_sc2143Val)
{
    uint8_t u8_regBuf[2] = {0};
    uint8_t u8_rdVal = 0;
    int32_t s32_result = 0;
    
    u8_regBuf[0] = u16_sc2143Reg >> 8;
    u8_regBuf[1] = u16_sc2143Reg & 0xff;

    I2C_Master_ReadData(SC2143_COMPONENT, SC2143_I2C_ADDR, u8_regBuf,2, &u8_rdVal, 1);
    s32_result = I2C_Master_WaitTillIdle(SC2143_COMPONENT, SC2143_I2C_MAX_DELAY);
    if(0 != s32_result) 
    {
        DLOG_Error("read reg error:reg=%x", u16_sc2143Reg);
        s32_result = -1;
    }
    else
    {
        ;
    }   

    *pu8_sc2143Val = u8_rdVal;

    return s32_result;
}

int32_t SC2143_DownloadFirmware(STRU_CAMERA_REG_VALUE *pst_sc2143, uint32_t u32_sc2143ArySize)
{
    register uint16_t u16_regAddr = 0;
    register uint8_t u8_val = 0;
    uint8_t u8_regVal = 0;
    uint32_t u32_i;
    int32_t s32_retVal = 0;

    for (u32_i = 0; u32_i < u32_sc2143ArySize; ++u32_i, ++pst_sc2143) 
    {
        u16_regAddr = pst_sc2143->u16_regAddr;
        u8_val = pst_sc2143->u8_val;

        s32_retVal = SC2143_WriteReg(u16_regAddr, u8_val);
        if (s32_retVal < 0)
        {
            goto err;
        }

    }
err:
    return s32_retVal;
}

void SC2143_ReadChipId(void)
{
    uint8_t SC2143_Chip_ID[1] = {0xFF};
    
    XC6130_ReadReg(0x36FF, &SC2143_Chip_ID[0]);
    DLOG_Warning("SC2143 chip id: 0x%02x", SC2143_Chip_ID[0]);
    if(0 == SC2143_Chip_ID[0])
    {
        DLOG_Warning("SC2143 chip id ok");
    }
    else
    {
        DLOG_Warning("SC2143 chip id error");
    }
}

void XC6130_SC2143_PinSet(void)
{
    HAL_GPIO_SetMode(SC2143_PWDN, HAL_GPIO_PIN_MODE2);    
    HAL_GPIO_OutPut(SC2143_PWDN);
    HAL_GPIO_SetPin(SC2143_PWDN,  HAL_GPIO_PIN_RESET);

    
    HAL_GPIO_SetMode(SC2143_RESET_B, HAL_GPIO_PIN_MODE2);    
    HAL_GPIO_OutPut(SC2143_RESET_B);
    HAL_GPIO_SetPin(SC2143_RESET_B,  HAL_GPIO_PIN_RESET);
    HAL_Delay(3);
    HAL_GPIO_SetPin(SC2143_RESET_B,  HAL_GPIO_PIN_SET);
}

void SwitchI2CToSc2143(void)
{
    HAL_I2C_MasterInit(SC2143_COMPONENT, SC2143_I2C_ADDR, HAL_I2C_FAST_SPEED);
    XC6130_I2cByPassOn();
    DLOG_Warning("SwitchI2CToSc2143...");
}

void SC2143_Init(uint8_t par_no)
{
    if (0 == par_no)  //20fps
    {
    uint32_t u32_sc2143ArSize = sizeof(SC2143_default_regs) /
                                    sizeof(SC2143_default_regs[0]);
    
    SC2143_DownloadFirmware(SC2143_default_regs, u32_sc2143ArSize);
    DLOG_Error("sc2143_setfor_1920108020fps");
    }
    else if(1 == par_no) //30fps
    {
    uint32_t u32_sc2143ArSize = sizeof(SC2143_regs_1080p30fps) /
                                    sizeof(SC2143_regs_1080p30fps[0]);
    
    SC2143_DownloadFirmware(SC2143_regs_1080p30fps, u32_sc2143ArSize);
    DLOG_Error("sc2143_setfor_1920108030fps");
    }
    else if(2 == par_no) //30fps 600fov
    {
    uint32_t u32_sc2143ArSize = sizeof(SC2143_regs_1080p30fps_600fov) /
                                    sizeof(SC2143_regs_1080p30fps_600fov[0]);
    
    SC2143_DownloadFirmware(SC2143_regs_1080p30fps_600fov, u32_sc2143ArSize);
    DLOG_Error("sc2143_setfor_1920108030fps_600fov");
    }
}
